<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Channel Error 恢复机制测试</title>
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .test-container {
            background: white;
            border-radius: 8px;
            padding: 20px;
            margin-bottom: 20px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .test-title {
            color: #333;
            border-bottom: 2px solid #007acc;
            padding-bottom: 10px;
            margin-bottom: 20px;
        }
        .test-button {
            background: #007acc;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 5px;
            cursor: pointer;
            margin: 5px;
            font-size: 14px;
        }
        .test-button:hover {
            background: #005a9e;
        }
        .test-button:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        .log-container {
            background: #f8f9fa;
            border: 1px solid #e9ecef;
            border-radius: 4px;
            padding: 15px;
            margin-top: 15px;
            max-height: 300px;
            overflow-y: auto;
            font-family: 'Courier New', monospace;
            font-size: 12px;
        }
        .log-entry {
            margin-bottom: 5px;
            padding: 2px 0;
        }
        .log-info { color: #007acc; }
        .log-success { color: #28a745; }
        .log-warning { color: #ffc107; }
        .log-error { color: #dc3545; }
        .status-indicator {
            display: inline-block;
            width: 12px;
            height: 12px;
            border-radius: 50%;
            margin-right: 8px;
        }
        .status-connected { background-color: #28a745; }
        .status-disconnected { background-color: #dc3545; }
        .status-reconnecting { background-color: #ffc107; }
        .test-scenario {
            border-left: 4px solid #007acc;
            padding-left: 15px;
            margin: 15px 0;
        }
        .metrics {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
            gap: 15px;
            margin-top: 20px;
        }
        .metric-card {
            background: #f8f9fa;
            padding: 15px;
            border-radius: 5px;
            text-align: center;
        }
        .metric-value {
            font-size: 24px;
            font-weight: bold;
            color: #007acc;
        }
        .metric-label {
            font-size: 12px;
            color: #666;
            margin-top: 5px;
        }
    </style>
</head>
<body>
    <div class="test-container">
        <h1 class="test-title">🔧 Channel Error 恢复机制测试</h1>
        
        <div class="test-scenario">
            <h3>连接状态</h3>
            <p>
                <span class="status-indicator status-disconnected" id="connectionStatus"></span>
                <span id="connectionText">未连接</span>
            </p>
        </div>

        <div class="test-scenario">
            <h3>测试场景</h3>
            <button class="test-button" onclick="testNormalFlow()">正常订阅流程</button>
            <button class="test-button" onclick="testChannelError()">模拟Channel Error</button>
            <button class="test-button" onclick="testNetworkInterruption()">模拟网络中断</button>
            <button class="test-button" onclick="testPageRefresh()">测试页面刷新恢复</button>
            <button class="test-button" onclick="testConcurrentCommands()">并发命令测试</button>
            <button class="test-button" onclick="clearLogs()">清空日志</button>
        </div>

        <div class="test-scenario">
            <h3>快速操作</h3>
            <button class="test-button" onclick="sendTestCommand()">发送测试命令</button>
            <button class="test-button" onclick="triggerFallback()">触发Fallback机制</button>
            <button class="test-button" onclick="checkPendingCommands()">检查待处理命令</button>
            <button class="test-button" onclick="forceRecovery()">强制恢复结果</button>
        </div>

        <div class="metrics">
            <div class="metric-card">
                <div class="metric-value" id="totalCommands">0</div>
                <div class="metric-label">总命令数</div>
            </div>
            <div class="metric-card">
                <div class="metric-value" id="successfulCommands">0</div>
                <div class="metric-label">成功命令</div>
            </div>
            <div class="metric-card">
                <div class="metric-value" id="failedCommands">0</div>
                <div class="metric-label">失败命令</div>
            </div>
            <div class="metric-card">
                <div class="metric-value" id="fallbackTriggers">0</div>
                <div class="metric-label">Fallback触发次数</div>
            </div>
        </div>

        <div class="log-container" id="logContainer">
            <div class="log-entry log-info">测试页面已加载，等待开始测试...</div>
        </div>
    </div>

    <script>
        // 测试统计
        let testMetrics = {
            totalCommands: 0,
            successfulCommands: 0,
            failedCommands: 0,
            fallbackTriggers: 0
        };

        // 日志函数
        function log(message, type = 'info') {
            const logContainer = document.getElementById('logContainer');
            const timestamp = new Date().toLocaleTimeString();
            const logEntry = document.createElement('div');
            logEntry.className = `log-entry log-${type}`;
            logEntry.textContent = `[${timestamp}] ${message}`;
            logContainer.appendChild(logEntry);
            logContainer.scrollTop = logContainer.scrollHeight;
        }

        // 更新指标
        function updateMetrics() {
            document.getElementById('totalCommands').textContent = testMetrics.totalCommands;
            document.getElementById('successfulCommands').textContent = testMetrics.successfulCommands;
            document.getElementById('failedCommands').textContent = testMetrics.failedCommands;
            document.getElementById('fallbackTriggers').textContent = testMetrics.fallbackTriggers;
        }

        // 更新连接状态
        function updateConnectionStatus(connected, message) {
            const statusIndicator = document.getElementById('connectionStatus');
            const statusText = document.getElementById('connectionText');
            
            if (connected) {
                statusIndicator.className = 'status-indicator status-connected';
                statusText.textContent = message || '已连接';
            } else {
                statusIndicator.className = 'status-indicator status-disconnected';
                statusText.textContent = message || '未连接';
            }
        }

        // 测试函数
        async function testNormalFlow() {
            log('开始测试正常订阅流程...', 'info');
            
            try {
                // 模拟正常命令发送
                const testCommand = `测试命令 - ${Date.now()}`;
                log(`发送测试命令: ${testCommand}`, 'info');
                
                testMetrics.totalCommands++;
                updateMetrics();
                
                // 这里应该调用实际的命令发送函数
                // 由于这是测试页面，我们模拟成功
                setTimeout(() => {
                    log('命令执行成功，订阅正常工作', 'success');
                    testMetrics.successfulCommands++;
                    updateMetrics();
                }, 2000);
                
            } catch (error) {
                log(`正常流程测试失败: ${error.message}`, 'error');
                testMetrics.failedCommands++;
                updateMetrics();
            }
        }

        async function testChannelError() {
            log('开始测试Channel Error恢复机制...', 'warning');
            
            try {
                // 模拟channel error
                log('模拟CHANNEL_ERROR事件...', 'warning');
                testMetrics.fallbackTriggers++;
                updateMetrics();
                
                // 模拟立即状态检查
                setTimeout(() => {
                    log('执行立即状态检查...', 'info');
                }, 1000);
                
                // 模拟fallback查询启动
                setTimeout(() => {
                    log('启动fallback查询机制 (5秒间隔)', 'info');
                }, 2000);
                
                // 模拟通过fallback获取结果
                setTimeout(() => {
                    log('通过fallback机制成功获取命令结果', 'success');
                    testMetrics.successfulCommands++;
                    updateMetrics();
                }, 6000);
                
            } catch (error) {
                log(`Channel Error测试失败: ${error.message}`, 'error');
                testMetrics.failedCommands++;
                updateMetrics();
            }
        }

        async function testNetworkInterruption() {
            log('开始测试网络中断恢复...', 'warning');
            
            updateConnectionStatus(false, '网络中断');
            
            setTimeout(() => {
                log('网络连接恢复', 'info');
                updateConnectionStatus(true, '连接已恢复');
                
                setTimeout(() => {
                    log('重新建立订阅连接', 'success');
                }, 1000);
            }, 3000);
        }

        async function testPageRefresh() {
            log('测试页面刷新恢复机制...', 'info');
            
            // 模拟有待处理命令
            const pendingCommands = [
                { id: 'test-1', text: '待处理命令1', timestamp: Date.now() - 5000 },
                { id: 'test-2', text: '待处理命令2', timestamp: Date.now() - 3000 }
            ];
            
            log(`发现 ${pendingCommands.length} 个待处理命令`, 'info');
            
            pendingCommands.forEach((cmd, index) => {
                setTimeout(() => {
                    log(`恢复命令 ${cmd.id}: ${cmd.text}`, 'success');
                    testMetrics.successfulCommands++;
                    updateMetrics();
                }, (index + 1) * 1000);
            });
        }

        async function testConcurrentCommands() {
            log('开始并发命令测试...', 'info');
            
            const commandCount = 5;
            testMetrics.totalCommands += commandCount;
            updateMetrics();
            
            for (let i = 1; i <= commandCount; i++) {
                setTimeout(() => {
                    log(`并发命令 ${i} 开始处理`, 'info');
                    
                    setTimeout(() => {
                        log(`并发命令 ${i} 完成`, 'success');
                        testMetrics.successfulCommands++;
                        updateMetrics();
                    }, Math.random() * 3000 + 1000);
                }, i * 200);
            }
        }

        async function sendTestCommand() {
            const command = `测试命令 ${Date.now()}`;
            log(`发送: ${command}`, 'info');
            testMetrics.totalCommands++;
            updateMetrics();
            
            // 模拟命令处理
            setTimeout(() => {
                log(`命令完成: ${command}`, 'success');
                testMetrics.successfulCommands++;
                updateMetrics();
            }, 2000);
        }

        async function triggerFallback() {
            log('手动触发Fallback机制...', 'warning');
            testMetrics.fallbackTriggers++;
            updateMetrics();
            
            setTimeout(() => {
                log('Fallback查询执行中...', 'info');
            }, 1000);
            
            setTimeout(() => {
                log('Fallback查询完成', 'success');
            }, 3000);
        }

        async function checkPendingCommands() {
            log('检查待处理命令...', 'info');
            
            // 模拟检查本地存储
            const pendingCount = Math.floor(Math.random() * 3);
            
            if (pendingCount === 0) {
                log('没有待处理命令', 'success');
            } else {
                log(`发现 ${pendingCount} 个待处理命令`, 'warning');
                
                for (let i = 1; i <= pendingCount; i++) {
                    setTimeout(() => {
                        log(`处理待处理命令 ${i}`, 'info');
                    }, i * 500);
                }
            }
        }

        async function forceRecovery() {
            log('开始强制恢复丢失的结果...', 'warning');
            
            setTimeout(() => {
                log('扫描最近24小时的已完成命令...', 'info');
            }, 500);
            
            setTimeout(() => {
                const recoveredCount = Math.floor(Math.random() * 3) + 1;
                log(`成功恢复 ${recoveredCount} 个命令结果`, 'success');
                testMetrics.successfulCommands += recoveredCount;
                updateMetrics();
            }, 2000);
        }

        function clearLogs() {
            const logContainer = document.getElementById('logContainer');
            logContainer.innerHTML = '<div class="log-entry log-info">日志已清空</div>';
        }

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            log('Channel Error恢复机制测试页面已加载', 'success');
            updateConnectionStatus(true, '测试环境已就绪');
            updateMetrics();
            
            // 模拟定期状态更新
            setInterval(() => {
                if (Math.random() < 0.1) { // 10%概率
                    log('定期健康检查: 连接正常', 'info');
                }
            }, 5000);
        });
    </script>
</body>
</html> 